home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 1 / Meeting Pearls Vol 1 (1994).iso / amok98-106 / amok104 / oberon-a / texts.lha / Oberon2.Report.Text < prev    next >
Text File  |  1993-12-01  |  56KB  |  1,507 lines

  1. The Programming Language Oberon-2
  2.  
  3. H. Mössenböck, N. Wirth
  4. Institut für Computersysteme, ETH Zürich
  5. October 1993
  6.  
  7.  
  8.  
  9. 1. Introduction
  10.  
  11. Oberon-2 is a general-purpose language in the tradition of Oberon and
  12. Modula-2. Its most important features are block structure, modularity,
  13. separate compilation, static typing with strong type checking (also
  14. across module boundaries), and type extension with type-bound
  15. procedures.
  16.  
  17. Type extension makes Oberon-2 an object-oriented language. An object is
  18. a variable of an abstract data type consisting of private data (its
  19. state) and procedures that operate on this data. Abstract data types are
  20. declared as extensible records. Oberon-2 covers most terms of
  21. object-oriented languages by the established vocabulary of imperative
  22. languages in order to minimize the number of notions for similar
  23. concepts.
  24.  
  25. This report is not intended as a programmer's tutorial. It is
  26. intentionally kept concise. Its function is to serve as a reference for
  27. programmers, implementors, and manual writers. What remains unsaid is
  28. mostly left so intentionally, either because it can be derived from
  29. stated rules of the language, or because it would require to commit the
  30. definition when a general commitment appears as unwise.
  31.  
  32. Appendix A defines some terms that are used to express the type checking
  33. rules of Oberon-2. Where they appear in the text, they are written in
  34. italics to indicate their special meaning (e.g. the same type).
  35.  
  36.  
  37. 2. Syntax
  38.  
  39. An extended Backus-Naur Formalism (EBNF) is used to describe the syntax
  40. of Oberon-2: Alternatives are separated by |. Brackets [ and ] denote
  41. optionality of the enclosed expression, and braces { and } denote its
  42. repetition (possibly 0 times). Non-terminal symbols start with an
  43. upper-case letter (e.g. Statement). Terminal symbols either start with a
  44. lower-case letter (e.g. ident), or are written all in upper-case letters
  45. (e.g. BEGIN), or are denoted by strings (e.g. ":=").
  46.  
  47.  
  48. 3. Vocabulary and Representation
  49.  
  50. The representation of (terminal) symbols in terms of characters is
  51. defined using the ASCII set. Symbols are identifiers, numbers, strings,
  52. operators, and delimiters. The following lexical rules must be observed:
  53. Blanks and line breaks must not occur within symbols (except in
  54. comments, and blanks in strings). They are ignored unless they are
  55. essential to separate two consecutive symbols. Capital and lower-case
  56. letters are considered as distinct.
  57.  
  58. 1. Identifiers are sequences of letters and digits. The first character
  59. must be a letter.
  60.  
  61. ident = letter {letter | digit}.
  62.  
  63. Examples:     x     Scan     Oberon2     GetSymbol     firstLetter
  64.  
  65. 2. Numbers are (unsigned) integer or real constants. The type of an
  66. integer constant is the minimal type to which the constant value belongs
  67. (see 6.1). If the constant is specified with the suffix H, the
  68. representation is hexadecimal otherwise the representation is decimal.
  69.  
  70. A real number always contains a decimal point. Optionally it may also
  71. contain a decimal scale factor. The letter E (or D) means "times ten to
  72. the power of". A real number is of type REAL, unless it has a scale
  73. factor containing the letter D. In this case it is of type LONGREAL.
  74.  
  75. number   = integer | real.
  76. integer   = digit {digit} | digit {hexDigit} "H".
  77. real   = digit {digit} "." {digit} [ScaleFactor].
  78. ScaleFactor   = ("E" | "D") ["+" | "-"] digit {digit}.
  79. hexDigit   = digit | "A" | "B" | "C" | "D" | "E" | "F".
  80. digit   = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9".
  81.  
  82. Examples:
  83. 1991  INTEGER  1991
  84. 0DH   SHORTINT  13
  85. 12.3  REAL  12.3
  86. 4.567E8   REAL  456700000
  87. 0.57712566D-6   LONGREAL  0.00000057712566
  88.  
  89. 3. Character constants are denoted by the ordinal number of the
  90. character in hexadecimal notation followed by the letter X.
  91.  
  92. character  = digit {hexDigit} "X".
  93.  
  94. 4. Strings are sequences of characters enclosed in single (') or double
  95. (") quote marks. The opening quote must be the same as the closing quote
  96. and must not occur within the string. The number of characters in a
  97. string is called its length. A string of length 1 can be used wherever a
  98. character constant is allowed and vice versa.
  99.  
  100. string  = ' " ' {char} ' " ' | " ' " {char} " ' ".
  101.  
  102. Examples:     "Oberon-2"     "Don't worry!"     "x"
  103.  
  104. 5. Operators and delimiters are the special characters, character pairs,
  105. or reserved words listed below. The reserved words consist exclusively
  106. of capital letters and cannot be used as identifiers.
  107.  
  108. +  :=  ARRAY  IMPORT  RETURN
  109. -  ^  BEGIN  IN  THEN
  110. *  =  BY  IS  TO
  111. /  #  CASE  LOOP  TYPE
  112. ~  <  CONST  MOD  UNTIL
  113. &  >  DIV  MODULE  VAR
  114. .  <=  DO  NIL  WHILE
  115. ,  >=  ELSE  OF  WITH
  116. ;  ..  ELSIF  OR
  117. |  :  END  POINTER
  118. (  )  EXIT  PROCEDURE
  119. [  ]  FOR  RECORD
  120. {  }  IF  REPEAT
  121.  
  122. 6. Comments may be inserted between any two symbols in a program. They
  123. are arbitrary character sequences opened by the bracket (* and closed by
  124. *). Comments may be nested. They do not affect the meaning of a program.
  125.  
  126.  
  127. 4. Declarations and scope rules
  128.  
  129. Every identifier occurring in a program must be introduced by a
  130. declaration, unless it is a predeclared identifier. Declarations also
  131. specify certain permanent properties of an object, such as whether it is
  132. a constant, a type, a variable, or a procedure. The identifier is then
  133. used to refer to the associated object.
  134.  
  135.   The scope of an object x extends textually from the point of its
  136. declaration to the end of the block (module, procedure, or record) to
  137. which the declaration belongs and hence to which the object is local. It
  138. excludes the scopes of equally named objects which are declared in
  139. nested blocks. The scope rules are:
  140.  
  141.   1.  No identifier may denote more than one object within a given scope
  142.     (i.e. no identifier may be declared twice in a block);
  143.   2.  An object may only be referenced within its scope;
  144.   3.  A type T of the form POINTER TO T1 (see 6.4) can be declared at a
  145.     point where T1 is still unknown. The declaration of T1 must follow
  146.     in the same block to which T is local;
  147.   4.  Identifiers denoting record fields (see 6.3) or type-bound
  148.     procedures (see 10.2) are valid in record designators only.
  149.  
  150. An identifier declared in a module block may be followed by an export
  151. mark (" * " or " - ") in its declaration to indicate that it is
  152. exported. An identifier x exported by a module M may be used in other
  153. modules, if they import M (see Ch.11). The identifier is then denoted as
  154. M.x in these modules and is called a qualified identifier. Identifiers
  155. marked with " - " in their declaration are read-only in importing
  156. modules.
  157.  
  158. Qualident   = [ident "."] ident.
  159. IdentDef   = ident [" * " | " - "].
  160.  
  161. The following identifiers are predeclared; their meaning is defined in
  162. the indicated sections:
  163.  
  164. ABS  (10.3)  LEN  (10.3)
  165. ASH  (10.3)  LONG  (10.3)
  166. BOOLEAN  (6.1)  LONGINT  (6.1)
  167. CAP  (10.3)  LONGREAL  (6.1)
  168. CHAR  (6.1)  MAX  (10.3)
  169. CHR  (10.3)  MIN  (10.3)
  170. COPY  (10.3)  NEW  (10.3)
  171. DEC  (10.3)  ODD  (10.3)
  172. ENTIER  (10.3)  ORD  (10.3)
  173. EXCL  (10.3)  REAL  (6.1)
  174. FALSE  (6.1)  SET  (6.1)
  175. HALT  (10.3)  SHORT  (10.3)
  176. INC  (10.3)  SHORTINT  (6.1)
  177. INCL  (10.3)  SIZE  (10.3)
  178. INTEGER  (6.1)  TRUE  (6.1)
  179.  
  180.  
  181. 5. Constant declarations
  182.  
  183. A constant declaration associates an identifier with a constant value.
  184.  
  185. ConstantDeclaration   = IdentDef "=" ConstExpression.
  186. ConstExpression   = Expression.
  187.  
  188. A constant expression is an expression that can be evaluated by a mere
  189. textual scan without actually executing the program. Its operands are
  190. constants (Ch.8) or predeclared functions (Ch.10.3) that can be
  191. evaluated at compile time. Examples of constant declarations are:
  192.  
  193. N = 100
  194. limit = 2*N - 1
  195. fullSet = {MIN(SET) .. MAX(SET)}
  196.  
  197.  
  198. 6. Type declarations
  199.  
  200. A data type determines the set of values which variables of that type
  201. may assume, and the operators that are applicable. A type declaration
  202. associates an identifier with a type. In the case of structured types
  203. (arrays and records) it also defines the structure of variables of this
  204. type. A structured type cannot contain itself.
  205.  
  206. TypeDeclaration   = IdentDef "=" Type.
  207. Type   = Qualident | ArrayType | RecordType | PointerType | ProcedureType.
  208.  
  209. Examples:
  210.  
  211. Table = ARRAY N OF REAL
  212. Tree = POINTER TO Node
  213. Node =  RECORD
  214.   key : INTEGER;
  215.   left, right: Tree
  216. END
  217. CenterTree = POINTER TO CenterNode
  218. CenterNode = RECORD (Node)
  219.   width: INTEGER;
  220.   subnode: Tree
  221. END
  222. Function = PROCEDURE(x: INTEGER): INTEGER
  223.  
  224.  
  225. 6.1 Basic types
  226.  
  227. The basic types are denoted by predeclared identifiers. The associated
  228. operators are defined in 8.2 and the predeclared function procedures in
  229. 10.3. The values of the given basic types are the following:
  230.  
  231. 1.  BOOLEAN  the truth values TRUE and FALSE
  232. 2.  CHAR  the characters of the extended ASCII set (0X .. 0FFX)
  233. 3.  SHORTINT  the integers between MIN(SHORTINT) and MAX(SHORTINT)
  234. 4.  INTEGER  the integers between MIN(INTEGER) and MAX(INTEGER)
  235. 5.  LONGINT  the integers between MIN(LONGINT) and MAX(LONGINT)
  236. 6.  REAL  the real numbers between MIN(REAL) and MAX(REAL)
  237. 7.  LONGREAL  the real numbers between MIN(LONGREAL) and MAX(LONGREAL)
  238. 8.  SET  the sets of integers between 0 and MAX(SET)
  239.  
  240. Types 3 to 5 are integer types, types 6 and 7 are real types, and
  241. together they are called numeric types. They form a hierarchy; the
  242. larger type includes (the values of) the smaller type:
  243.  
  244.   LONGREAL  >=  REAL  >=  LONGINT  >=  INTEGER  >=  SHORTINT
  245.  
  246.  
  247. 6.2 Array types
  248.  
  249. An array is a structure consisting of a number of elements which are all
  250. of the same type, called the element type. The number of elements of an
  251. array is called its length. The elements of the array are designated by
  252. indices, which are integers between 0 and the length minus 1.
  253.  
  254. ArrayType   = ARRAY [Length {"," Length}] OF Type.
  255. Length   = ConstExpression.
  256.  
  257. A type of the form
  258.  
  259.   ARRAY L0, L1, ..., Ln OF T
  260.  
  261. is understood as an abbreviation of
  262.  
  263.   ARRAY L0 OF
  264.     ARRAY L1 OF
  265.     ...
  266.       ARRAY Ln OF T
  267.  
  268. Arrays declared without length are called open arrays. They are
  269. restricted to pointer base types (see 6.4), element types of open array
  270. types, and formal parameter types (see 10.1). Examples:
  271.  
  272.   ARRAY 10, N OF INTEGER
  273.   ARRAY OF CHAR
  274.  
  275.  
  276. 6.3 Record types
  277.  
  278. A record type is a structure consisting of a fixed number of elements,
  279. called fields, with possibly different types. The record type
  280. declaration specifies the name and type of each field. The scope of the
  281. field identifiers extends from the point of their declaration to the end
  282. of the record type, but they are also visible within designators
  283. referring to elements of record variables (see 8.1). If a record type is
  284. exported, field identifiers that are to be visible outside the declaring
  285. module must be marked. They are called public fields; unmarked elements
  286. are called private fields.
  287.  
  288. RecordType   = RECORD ["("BaseType")"] FieldList {";" FieldList} END.
  289. BaseType   = Qualident.
  290. FieldList   = [IdentList ":" Type ].
  291.  
  292. Record types are extensible, i.e. a record type can be declared as an
  293. extension of another record type. In the example
  294.  
  295.   T0 = RECORD x: INTEGER END
  296.   T1 = RECORD (T0) y: REAL END
  297.  
  298. T1 is a (direct) extension of T0 and T0 is the (direct) base type of T1
  299. (see App. A). An extended type T1 consists of the fields of its base
  300. type and of the fields which are declared in T1. All identifiers
  301. declared in the extended record must be different from the identifiers
  302. declared in its base type record(s).
  303.  
  304. Examples of record type declarations:
  305.  
  306. RECORD
  307.   day, month, year: INTEGER
  308. END
  309.  
  310. RECORD
  311.   name, firstname: ARRAY 32 OF CHAR;
  312.   age: INTEGER;
  313.   salary: REAL
  314. END
  315.  
  316.  
  317. 6.4 Pointer types
  318.  
  319. Variables of a pointer type P assume as values pointers to variables of
  320. some type T. T is called the pointer base type of P and must be a record
  321. or array type. Pointer types adopt the extension relation of their
  322. pointer base types: if a type T1 is an extension of T, and P1 is of type
  323. POINTER TO T1, then P1 is also an extension of P.
  324.  
  325.   PointerType = POINTER TO Type.
  326.  
  327. If p is a variable of type P = POINTER TO T, a call of the predeclared
  328. procedure NEW(p) (see 10.3) allocates a variable of type T in free
  329. storage. If T is a record type or an array type with fixed length, the
  330. allocation has to be done with NEW(p); if T is an n-dimensional open
  331. array type the allocation has to be done with NEW(p, e0, ..., en-1)
  332. where T is allocated with lengths given by the expressions e0, ...,
  333. en-1. In either case a pointer to the allocated variable is assigned to
  334. p. p is of type P. The referenced  variable p^ (pronounced as
  335. p-referenced) is of type T. Any pointer variable may assume the value
  336. NIL, which points to no variable at all.
  337.  
  338.  
  339. 6.5 Procedure types
  340.  
  341. Variables of a procedure type T have a procedure (or NIL) as value. If a
  342. procedure P is assigned to a variable of type T, the formal parameter
  343. lists (see Ch. 10.1) of P and T must match (see App. A). P must not be a
  344. predeclared or type-bound procedure nor may it be local to another
  345. procedure.
  346.  
  347.   ProcedureType = PROCEDURE [FormalParameters].
  348.  
  349.  
  350. 7. Variable declarations
  351.  
  352. Variable declarations introduce variables by defining an identifier and
  353. a data type for them.
  354.  
  355.   VariableDeclaration = IdentList ":" Type.
  356.  
  357. Record and pointer variables have both a static type (the type with
  358. which they are declared - simply called their type) and a dynamic type
  359. (the type of their value at run time). For pointers and variable
  360. parameters of record type the dynamic type may be an extension of their
  361. static type. The static type determines which fields of a record are
  362. accessible. The dynamic type is used to call type-bound procedures (see
  363. 10.2).
  364.  
  365. Examples of variable declarations (refer to examples in Ch. 6):
  366.  
  367. i, j, k: INTEGER
  368. x, y: REAL
  369. p, q: BOOLEAN
  370. s: SET
  371. F: Function
  372. a: ARRAY 100 OF REAL
  373. w: ARRAY 16 OF RECORD
  374.     name: ARRAY 32 OF CHAR;
  375.     count: INTEGER
  376.   END
  377. t, c: Tree
  378.  
  379.  
  380. 8. Expressions
  381.  
  382. Expressions are constructs denoting rules of computation whereby
  383. constants and current values of variables are combined to compute other
  384. values by the application of operators and function procedures.
  385. Expressions consist of operands and operators. Parentheses may be used
  386. to express specific associations of operators and operands.
  387.  
  388.  
  389. 8.1 Operands
  390.  
  391. With the exception of set constructors and literal constants (numbers,
  392. character constants, or strings), operands are denoted by designators. A
  393. designator consists of an identifier referring to a constant, variable,
  394. or procedure. This identifier may possibly be qualified by a module
  395. identifier (see Ch. 4 and 11) and may be followed by selectors if the
  396. designated object is an element of a structure.
  397.  
  398. Designator   = Qualident {"." ident | "[" ExpressionList "]" | "^" |
  399.     "(" Qualident ")"}.
  400. ExpressionList   = Expression {"," Expression}.
  401.  
  402. If a designates an array, then a[e] denotes that element of a whose
  403. index is the current value of the expression e. The type of e must be an
  404. integer type. A designator of the form a[e0, e1, ..., en] stands for
  405. a[e0][e1]...[en]. If r designates a record, then r.f denotes the field f
  406. of r or the procedure f bound to the dynamic type of r (Ch. 10.2). If p
  407. designates a pointer, p^ denotes the variable which is referenced by p.
  408. The designators p^.f and p^[e] may be abbreviated as p.f and p[e], i.e.
  409. record and array selectors imply dereferencing. If a or r are read-only,
  410. then also a[e] and r.f are read-only.
  411.  
  412.   A type guard v(T) asserts that the dynamic type of v is T (or an
  413. extension of T), i.e. program execution is aborted, if the dynamic type
  414. of v is not T (or an extension of T). Within the designator, v is then
  415. regarded as having the static type T. The guard is applicable, if
  416.  
  417.   1.  v is a variable parameter of record type or v is a pointer, and if
  418.   2.  T is an extension of the static type of v
  419.  
  420. If the designated object is a constant or a variable, then the
  421. designator refers to its current value. If it is a procedure, the
  422. designator refers to that procedure unless it is followed by a (possibly
  423. empty) parameter list in which case it implies an activation of that
  424. procedure and stands for the value resulting from its execution. The
  425. actual parameters must correspond to the formal parameters as in proper
  426. procedure calls (see 10.1).
  427.  
  428. Examples of designators (refer to examples in Ch.7):
  429.  
  430. i  (INTEGER)
  431. a[i]  (REAL)
  432. w[3].name[i]  (CHAR)
  433. t.left.right  (Tree)
  434. t(CenterTree).subnode  (Tree)
  435.  
  436.  
  437. 8.2 Operators
  438.  
  439. Four classes of operators with different precedences (binding strengths)
  440. are syntactically distinguished in expressions. The operator ~ has the
  441. highest precedence, followed by multiplication operators, addition
  442. operators, and relations. Operators of the same precedence associate
  443. from left to right. For example, x-y-z stands for (x-y)-z.
  444.  
  445. Expression   = SimpleExpression [Relation SimpleExpression].
  446. SimpleExpression  = ["+" | "-"] Term {AddOperator Term}.
  447. Term   = Factor {MulOperator Factor}.
  448. Factor   = Designator [ActualParameters] |
  449.       number | character | string | NIL | Set | "(" Expression ")" |
  450.       "~" Factor.
  451. Set   = "{" [Element {"," Element}] "}".
  452. Element   = Expression [".." Expression].
  453. ActualParameters   = "(" [ExpressionList] ")".
  454. Relation   = "=" | "#" | "<" | "<=" | ">" | ">=" | IN | IS.
  455. AddOperator   = "+" | "-" | OR.
  456. MulOperator   = "*" | "/" | DIV | MOD | "&".
  457.  
  458. The available operators are listed in the following tables. Some
  459. operators are applicable to operands of various types, denoting
  460. different operations. In these cases, the actual operation is identified
  461. by the type of the operands. The operands must be expression compatible
  462. with respect to the operator (see App. A).
  463.  
  464. 8.2.1 Logical operators
  465.  
  466. OR  logical disjunction   p OR q    "if p then TRUE, else q"
  467. &  logical conjunction   p & q    "if p then q, else FALSE"
  468. ~  negation   ~ p    "not p"
  469.  
  470. These operators apply to BOOLEAN operands and yield a BOOLEAN result.
  471.  
  472. 8.2.2 Arithmetic operators
  473.  
  474. +  sum
  475. -  difference
  476. *  product
  477. /  real quotient
  478. DIV  integer quotient
  479. MOD  modulus
  480.  
  481. The operators +, -, *, and / apply to operands of numeric types. The
  482. type of the result is the type of that operand which includes the type
  483. of the other operand, except for division (/), where the result is the
  484. smallest real type which includes both operand types. When used as
  485. monadic operators, - denotes sign inversion and + denotes the identity
  486. operation. The operators DIV and MOD apply to integer operands only.
  487. They are related by the following formulas defined for any x and
  488. positive divisors y:
  489.  
  490. x = (x DIV y) * y + (x MOD y)
  491. 0 <= (x MOD y) < y
  492.  
  493. Examples:
  494. x  y  x DIV y  x MOD y
  495. 5  3  1  2
  496. -5  3  -2  1
  497.  
  498. 8.2.3 Set Operators
  499.  
  500. +  union
  501. -  difference (x - y = x * (-y))
  502. *  intersection
  503. /  symmetric set difference (x / y = (x-y) + (y-x))
  504.  
  505. Set operators apply to operands of type SET and yield a result of type
  506. SET. The monadic minus sign denotes the complement of x, i.e. -x denotes
  507. the set of integers between 0 and MAX(SET) which are not elements of x.
  508. Set operators are not associative ((a+b)-c # a+(b-c)).
  509.  
  510. A set constructor defines the value of a set by listing its elements
  511. between curly brackets. The elements must be integers in the range
  512. 0..MAX(SET). A range a..b denotes all integers in the interval [a, b].
  513.  
  514. 8.2.4 Relations
  515.  
  516. =  equal
  517. #  unequal
  518. <  less
  519. <=  less or equal
  520. >  greater
  521. >=  greater or equal
  522. IN  set membership
  523. IS  type test
  524.  
  525. Relations yield a BOOLEAN result. The relations =, #, <, <=, >, and >=
  526. apply to the numeric types, CHAR, strings, and character arrays
  527. containing 0X as a terminator. The relations = and # also apply to
  528. BOOLEAN and SET, as well as to pointer and procedure types (including
  529. the value NIL). x IN s stands for "x is an element of s". x must be of
  530. an integer type, and s of type SET. v IS T stands for "the dynamic type
  531. of v is T (or an extension of T)" and is called a type test. It is
  532. applicable if
  533.  
  534. 1.  v is a variable parameter of record type or v is a pointer, and if
  535. 2.  T is an extension of the static type of v
  536.  
  537. Examples of expressions (refer to examples in Ch.7):
  538.  
  539. 1991  INTEGER
  540. i DIV 3  INTEGER
  541. ~p OR q  BOOLEAN
  542. (i+j) * (i-j)  INTEGER
  543. s - {8, 9, 13}  SET
  544. i + x  REAL
  545. a[i+j] * a[i-j]  REAL
  546. (0<=i) & (i<100)  BOOLEAN
  547. t.key = 0  BOOLEAN
  548. k IN {i..j-1}  BOOLEAN
  549. w[i].name <= "John"  BOOLEAN
  550. t IS CenterTree  BOOLEAN
  551.  
  552.  
  553. 9. Statements
  554.  
  555. Statements denote actions. There are elementary and structured
  556. statements. Elementary statements are not composed of any parts that are
  557. themselves statements. They are the assignment, the procedure call, the
  558. return, and the exit statement. Structured statements are composed of
  559. parts that are themselves statements. They are used to express
  560. sequencing and conditional, selective, and repetitive execution. A
  561. statement may also be empty, in which case it denotes no action. The
  562. empty statement is included in order to relax punctuation rules in
  563. statement sequences.
  564.  
  565.   Statement =
  566.     [ Assignment | ProcedureCall | IfStatement | CaseStatement |
  567.       WhileStatement | RepeatStatement | ForStatement | LoopStatement |
  568.       WithStatement | EXIT | RETURN [Expression] ].
  569.  
  570.  
  571. 9.1 Assignments
  572.  
  573. Assignments replace the current value of a variable by a new value
  574. specified by an expression. The expression must be assignment compatible
  575. with the variable (see App. A). The assignment operator is written as
  576. ":=" and pronounced as becomes.
  577.  
  578.   Assignment = Designator ":=" Expression.
  579.  
  580. If an expression e of type Te is assigned to a variable v of type Tv,
  581. the following happens:
  582.  
  583.   1.  if Tv and Te are record types, only those fields of Te are
  584.     assigned which also belong to Tv (projection); the dynamic type of v
  585.     must be the same as the static type of v and  is not changed by the
  586.     assignment;
  587.   2.  if Tv and Te are pointer types, the dynamic type of v becomes the
  588.     dynamic type of e;
  589.   3.  if Tv is ARRAY n OF CHAR and e is a string of length m<n, v[i]
  590.     becomes ei for i = 0..m-1 and v[m] becomes 0X.
  591.  
  592. Examples of assignments (refer to examples in Ch.7):
  593.  
  594. i := 0
  595. p := i = j
  596. x := i + 1
  597. k := log2(i+j)
  598. F := log2    (* see 10.1 *)
  599. s := {2, 3, 5, 7, 11, 13}
  600. a[i] := (x+y) * (x-y)
  601. t.key := i
  602. w[i+1].name := "John"
  603. t := c
  604.  
  605. 9.2 Procedure calls
  606.  
  607. A procedure call activates a procedure. It may contain a list of actual
  608. parameters which replace the corresponding formal parameters defined in
  609. the procedure declaration (see Ch. 10). The correspondence is
  610. established by the positions of the parameters in the actual and formal
  611. parameter lists. There are two kinds of parameters: variable and value
  612. parameters.
  613.  
  614. If a formal parameter is a variable parameter, the corresponding actual
  615. parameter must be a designator denoting a variable. If it denotes an
  616. element of a structured variable, the component selectors are evaluated
  617. when the formal/actual parameter substitution takes place, i.e. before
  618. the execution of the procedure. If a formal parameter is a value
  619. parameter, the corresponding actual parameter must be an expression.
  620. This expression is evaluated before the procedure activation, and the
  621. resulting value is assigned to the formal parameter (see also 10.1).
  622.  
  623.   ProcedureCall = Designator [ActualParameters].
  624.  
  625. Examples:
  626.  
  627. WriteInt(i*2+1)  (* see 10.1 *)
  628. INC(w[k].count)
  629. t.Insert("John")  (* see 11 *)
  630.  
  631.  
  632. 9.3 Statement sequences
  633.  
  634. Statement sequences denote the sequence of actions specified by the
  635. component statements which are separated by semicolons.
  636.  
  637.   StatementSequence = Statement {";" Statement}.
  638.  
  639.  
  640. 9.4 If statements
  641.  
  642.   IfStatement =
  643.     IF Expression THEN StatementSequence
  644.     {ELSIF Expression THEN StatementSequence}
  645.     [ELSE StatementSequence]
  646.     END.
  647.  
  648. If statements specify the conditional execution of guarded statement
  649. sequences. The Boolean expression preceding a statement sequence is
  650. called its guard. The guards are evaluated in sequence of occurrence,
  651. until one evaluates to TRUE, whereafter its associated statement
  652. sequence is executed. If no guard is satisfied, the statement sequence
  653. following the symbol ELSE is executed, if there is one.
  654.  
  655. Example:
  656.  
  657. IF (ch >= "A") & (ch <= "Z") THEN ReadIdentifier
  658. ELSIF (ch >= "0") & (ch <= "9") THEN ReadNumber
  659. ELSIF (ch = " ' ") OR (ch = ' " ') THEN ReadString
  660. ELSE SpecialCharacter
  661. END
  662.  
  663.  
  664. 9.5 Case statements
  665.  
  666. Case statements specify the selection and execution of a statement
  667. sequence according to the value of an expression. First the case
  668. expression is evaluated, then that statement sequence is executed whose
  669. case label list contains the obtained value. The case expression must
  670. either be of an integer type that includes the types of all case labels,
  671. or both the case expression and the case labels must be of type CHAR.
  672. Case labels are constants, and no value must occur more than once. If
  673. the value of the expression does not occur as a label of any case, the
  674. statement sequence following the symbol ELSE is selected, if there is
  675. one, otherwise the program is aborted.
  676.  
  677. CaseStatement   = CASE Expression OF Case {"|" Case} [ELSE
  678.   StatementSequence] END.
  679. Case   = [CaseLabelList ":" StatementSequence].
  680. CaseLabelList   = CaseLabels {"," CaseLabels}.
  681. CaseLabels   = ConstExpression [".." ConstExpression].
  682.  
  683. Example:
  684.  
  685. CASE ch OF
  686.   "A" .. "Z": ReadIdentifier
  687. |  "0" .. "9": ReadNumber
  688. |  " ' ", ' " ': ReadString
  689. ELSE SpecialCharacter
  690. END
  691.  
  692.  
  693. 9.6 While statements
  694.  
  695. While statements specify the repeated execution of a statement sequence
  696. while the Boolean expression (its guard) yields TRUE. The guard is
  697. checked before every execution of the statement sequence.
  698.  
  699.   WhileStatement = WHILE Expression DO StatementSequence END.
  700.  
  701. Examples:
  702. WHILE i > 0 DO i := i DIV 2; k := k + 1 END
  703. WHILE (t # NIL) & (t.key # i) DO t := t.left END
  704.  
  705.  
  706. 9.7 Repeat statements
  707.  
  708. A repeat statement specifies the repeated execution of a statement
  709. sequence until a condition specified by a Boolean expression is
  710. satisfied. The statement sequence is executed at least once.
  711.  
  712.   RepeatStatement = REPEAT StatementSequence UNTIL Expression.
  713.  
  714.  
  715. 9.8 For statements
  716.  
  717. A for statement specifies the repeated execution of a statement sequence
  718. while a progression of values is assigned to an integer variable called
  719. the control variable of the for statement.
  720.  
  721.   ForStatement = FOR ident ":=" Expression TO Expression [BY
  722.     ConstExpression] DO StatementSequence END.
  723.  
  724. The statement
  725.  
  726.   FOR v := beg TO end BY step DO statements END
  727.  
  728. is equivalent to
  729.  
  730. temp := end; v := beg;
  731. IF step > 0 THEN
  732.   WHILE v <= temp DO statements; v := v + step END
  733. ELSE
  734.   WHILE v >= temp DO statements; v := v + step END
  735. END
  736.  
  737. temp has the same type as v. step must be a nonzero constant expression.
  738. If step is not specified, it is assumed to be 1.
  739.  
  740. Examples:
  741. FOR i := 0 TO 79 DO k := k + a[i] END
  742. FOR i := 79 TO 1 BY -1 DO a[i] := a[i-1] END
  743.  
  744.  
  745. 9.9 Loop statements
  746.  
  747. A loop statement specifies the repeated execution of a statement
  748. sequence. It is terminated upon execution of an exit statement within
  749. that sequence (see 9.10).
  750.  
  751.   LoopStatement = LOOP StatementSequence END.
  752.  
  753. Example:
  754. LOOP
  755.   ReadInt(i);
  756.   IF i < 0 THEN EXIT END;
  757.   WriteInt(i)
  758. END
  759.  
  760. Loop statements are useful to express repetitions with several exit
  761. points or cases where the exit condition is in the middle of the
  762. repeated statement sequence.
  763.  
  764.  
  765. 9.10 Return and exit statements
  766.  
  767. A return statement indicates the termination of a procedure. It is
  768. denoted by the symbol RETURN, followed by an expression if the procedure
  769. is a function procedure. The type of the expression must be assignment
  770. compatible (see App. A) with the result type specified in the procedure
  771. heading (see Ch.10).
  772.  
  773.   Function procedures require the presence of a return statement
  774. indicating the result value. In proper procedures, a return statement is
  775. implied by the end of the procedure body. Any explicit return statement
  776. therefore appears as an additional (probably exceptional) termination
  777. point.
  778.  
  779.   An exit statement is denoted by the symbol EXIT. It specifies
  780. termination of the enclosing loop statement and continuation with the
  781. statement following that loop statement. Exit statements are
  782. contextually, although not syntactically associated with the loop
  783. statement which contains them.
  784.  
  785.  
  786. 9.11 With statements
  787.  
  788. With statements execute a statement sequence depending on the result of
  789. a type test and apply a type guard to every occurrence of the tested
  790. variable within this statement sequence.
  791.  
  792. WithStatement   = WITH Guard DO StatementSequence {"|" Guard DO StatementSequence}
  793.     [ELSE StatementSequence] END.
  794. Guard  = Qualident ":" Qualident.
  795.  
  796. If v is a variable parameter of record type or a pointer variable, and
  797. if it is of a static type T0, the statement
  798.  
  799.   WITH v: T1 DO S1 | v: T2 DO S2 ELSE S3 END
  800.  
  801. has the following meaning: if the dynamic type of v is T1, then the
  802. statement sequence S1 is executed where v is regarded as if it had the
  803. static type T1; else if the dynamic type of v is T2, then S2 is executed
  804. where v is regarded as if it had the static type T2; else S3 is
  805. executed. T1 and T2 must be extensions of T0. If no type test is
  806. satisfied and if an else clause is missing the program is aborted.
  807.  
  808. Example:
  809.   WITH t: CenterTree DO i := t.width; c := t.subnode END
  810.  
  811.  
  812. 10. Procedure declarations
  813.  
  814. A procedure declaration consists of a procedure heading and a procedure
  815. body. The heading specifies the procedure identifier and the formal
  816. parameters. For type-bound procedures it also specifies the receiver
  817. parameter. The body contains declarations and statements. The procedure
  818. identifier is repeated at the end of the procedure declaration.
  819.  
  820.   There are two kinds of procedures: proper procedures and function
  821. procedures. The latter are activated by a function designator as a
  822. constituent of an expression and yield a result that is an operand of
  823. the expression. Proper procedures are activated by a procedure call. A
  824. procedure is a function procedure if its formal parameters specify a
  825. result type. The body of a function procedure must contain a return
  826. statement which defines its result.
  827.  
  828.   All constants, variables, types, and procedures declared within a
  829. procedure body are local to the procedure. Since procedures may be
  830. declared as local objects too, procedure declarations may be nested. The
  831. call of a procedure within its declaration implies recursive activation.
  832.  
  833.   Objects declared in the environment of the procedure are also visible
  834. in those parts of the procedure in which they are not concealed by a
  835. locally declared object with the same name.
  836.  
  837. ProcedureDeclaration  = ProcedureHeading ";" ProcedureBody ident.
  838. ProcedureHeading   = PROCEDURE [Receiver] IdentDef [FormalParameters].
  839. ProcedureBody   = DeclarationSequence [BEGIN StatementSequence] END.
  840. DeclarationSequence   =
  841.   {CONST {ConstantDeclaration ";"} | TYPE {TypeDeclaration ";"} | VAR {VariableDeclaration
  842. ";"} }
  843.   {ProcedureDeclaration ";" | ForwardDeclaration ";"}.
  844. ForwardDeclaration   = PROCEDURE " ^ " [Receiver] IdentDef [FormalParameters].
  845.  
  846. If a procedure declaration specifies a receiver parameter, the procedure
  847. is considered to be bound to a type (see 10.2). A forward declaration
  848. serves to allow forward references to a procedure whose actual
  849. declaration appears later in the text. The formal parameter lists of the
  850. forward declaration and the actual declaration must match (see App. A).
  851.  
  852.  
  853. 10.1 Formal parameters
  854.  
  855. Formal parameters are identifiers declared in the formal parameter list
  856. of a procedure. They correspond to actual parameters specified in the
  857. procedure call. The correspondence between formal and actual parameters
  858. is established when the procedure is called. There are two kinds of
  859. parameters, value and variable parameters, indicated in the formal
  860. parameter list by the absence or presence of the keyword VAR. Value
  861. parameters are local variables to which the value of the corresponding
  862. actual parameter is assigned as an initial value. Variable parameters
  863. correspond to actual parameters that are variables, and they stand for
  864. these variables. The scope of a formal parameter extends from its
  865. declaration to the end of the procedure block in which it is declared. A
  866. function procedure without parameters must have an empty parameter list.
  867. It must be called by a function designator whose actual parameter list
  868. is empty too. The result type of a procedure can be neither a record nor
  869. an array.
  870.  
  871. FormalParameters  = "(" [FPSection {";" FPSection}] ")" [":" Qualident].
  872. FPSection   = [VAR] ident {"," ident} ":" Type.
  873.  
  874. Let Tf be the type of a formal parameter f (not an open array) and Ta
  875. the type of the corresponding actual parameter a. For variable
  876. parameters, Ta must be the same as Tf, or Tf must be a record type and
  877. Ta an extension of Tf. For value parameters, a must be assignment
  878. compatible with f (see App. A).
  879.  
  880.   If Tf is an open array , then a must be array compatible with f (see
  881. App. A). The lengths of f are taken from a.
  882.  
  883. Examples of procedure declarations:
  884.  
  885. PROCEDURE ReadInt(VAR x: INTEGER);
  886.   VAR i: INTEGER; ch: CHAR;
  887. BEGIN i := 0; Read(ch);
  888.   WHILE ("0" <= ch) & (ch <= "9") DO
  889.     i := 10*i + (ORD(ch)-ORD("0")); Read(ch)
  890.   END;
  891.   x := i
  892. END ReadInt
  893.  
  894. PROCEDURE WriteInt(x: INTEGER); (*0 <= x <100000*)
  895.   VAR i: INTEGER; buf: ARRAY 5 OF INTEGER;
  896. BEGIN i := 0;
  897.   REPEAT buf[i] := x MOD 10; x := x DIV 10; INC(i) UNTIL x = 0;
  898.   REPEAT DEC(i); Write(CHR(buf[i] + ORD("0"))) UNTIL i = 0
  899. END WriteInt
  900.  
  901. PROCEDURE WriteString(s: ARRAY OF CHAR);
  902.   VAR i: INTEGER;
  903. BEGIN i := 0;
  904.   WHILE (i < LEN(s)) & (s[i] # 0X) DO Write(s[i]); INC(i) END
  905. END WriteString;
  906.  
  907.  
  908. PROCEDURE log2(x: INTEGER): INTEGER;
  909.   VAR y: INTEGER; (*assume x>0*)
  910. BEGIN
  911.   y := 0; WHILE x > 1 DO x := x DIV 2; INC(y) END;
  912.   RETURN y
  913. END log2
  914.  
  915.  
  916. 10.2 Type-bound procedures
  917.  
  918. Globally declared procedures may be associated with a record type
  919. declared in the same module. The procedures are said to be bound to the
  920. record type. The binding is expressed by the type of the receiver in the
  921. heading of a procedure declaration.  The receiver may be either a
  922. variable parameter of record type T or a value parameter of type POINTER
  923. TO T (where T is a record type). The procedure is bound to the type T
  924. and is considered local to it.
  925.  
  926. ProcedureHeading  = PROCEDURE [Receiver] IdentDef [FormalParameters].
  927. Receiver   = "(" [VAR] ident ":" ident ")".
  928.  
  929. If a procedure P is bound to a type T0, it is implicitly also bound to
  930. any type T1 which is an extension of T0. However, a procedure P' (with
  931. the same name as P) may be explicitly bound to T1 in which case it
  932. overrides the binding of P. P' is considered a redefinition of P for T1.
  933. The formal parameters of P and P' must match (see App. A). If P and T1
  934. are exported (see Chapter 4) P' must be exported too.
  935.  
  936.   If v is a designator and P is a type-bound procedure, then v.P denotes
  937. that procedure P which is bound to the dynamic type of v. Note, that
  938. this may be a different procedure than the one bound to the static type
  939. of v. v is passed to P's receiver according to the parameter passing
  940. rules specified in Chapter 10.1.
  941.  
  942.   If r is a receiver parameter declared with type T, r.P^ denotes the
  943. (redefined) procedure P bound to the base type of T. In a forward
  944. declaration of a type-bound procedure the receiver parameter must be of
  945. the same type as in the actual procedure declaration. The formal
  946. parameter lists of both declarations must match (App. A).
  947.  
  948. Examples:
  949.  
  950. PROCEDURE (t: Tree) Insert (node: Tree);
  951.   VAR p, father: Tree;
  952. BEGIN p := t;
  953.   REPEAT father := p;
  954.     IF node.key = p.key THEN RETURN END;
  955.     IF node.key < p.key THEN p := p.left ELSE p := p.right END
  956.   UNTIL p = NIL;
  957.   IF node.key < father.key THEN father.left := node ELSE father.right := node
  958. END;
  959.   node.left := NIL; node.right := NIL
  960. END Insert;
  961.  
  962. PROCEDURE (t: CenterTree) Insert (node: Tree);  (*redefinition*)
  963. BEGIN
  964.   WriteInt(node(CenterTree).width);
  965.   t.Insert^ (node)  (* calls the Insert procedure bound to Tree *)
  966. END Insert;
  967.  
  968.  
  969. 10.3 Predeclared procedures
  970.  
  971. The following table lists the predeclared procedures. Some are generic
  972. procedures, i.e. they apply to several types of operands. v stands for a
  973. variable, x and n for expressions, and T for a type.
  974.  
  975. Function procedures
  976.  
  977. Name  Argument type  Result type  Function
  978.  
  979. ABS(x)  numeric type  type of x  absolute value
  980. ASH(x, n)  x, n: integer type  LONGINT  arithmetic shift (x * 2n)
  981. CAP(x)  CHAR  CHAR  x is letter: corresponding capital letter
  982. CHR(x)  integer type  CHAR  character with ordinal number x
  983. ENTIER(x)  real type  LONGINT  largest integer not greater than x
  984. LEN(v, n)  v: array; n: integer const.  LONGINT  length of v in dimension n
  985. (first dimension = 0)
  986. LEN(v)  v: array  LONGINT  equivalent to LEN(v, 0)
  987. LONG(x)  SHORTINT  INTEGER  identity
  988.   INTEGER  LONGINT
  989.   REAL  LONGREAL
  990. MAX(T)  T = basic type  T  maximum value of type T
  991.   T = SET  INTEGER  maximum element of a set
  992. MIN(T)  T = basic type  T  minimum value of type T
  993.   T = SET  INTEGER  0
  994. ODD(x)  integer type  BOOLEAN  x MOD 2 = 1
  995. ORD(x)  CHAR  INTEGER  ordinal number of x
  996. SHORT(x)  LONGINT  INTEGER  identity
  997.   INTEGER  SHORTINT  identity
  998.   LONGREAL  REAL  identity (truncation possible)
  999. SIZE(T)  any type  integer type  number of bytes required by T
  1000.  
  1001. Proper procedures
  1002.  
  1003. Name  Argument types  Function
  1004.  
  1005. ASSERT(x)  x: Boolean expression  terminate program execution if not x
  1006. ASSERT(x, n)   x: Boolean expression; n: integer constant  terminate program
  1007. execution if not x
  1008. COPY(x, v)  x: character array, string; v: character array  v := x
  1009. DEC(v)  integer type  v := v - 1
  1010. DEC(v, n)  v, n: integer type  v := v - n
  1011. EXCL(v, x)  v: SET; x: integer type  v := v - {x}
  1012. HALT(n)  integer constant  terminate program execution
  1013. INC(v)  integer type  v := v + 1
  1014. INC(v, n)  v, n: integer type  v := v + n
  1015. INCL(v, x)  v: SET; x: integer type  v := v + {x}
  1016. NEW(v)  pointer to record or fixed array  allocate v ^
  1017. NEW(v, x0, ..., xn) v: pointer to open array; xi: integer type  allocate v ^
  1018. with lengths x0.. xn
  1019.  
  1020. COPY allows the assignment of a string or a character array containing a
  1021. terminating 0X to another character array. If necessary, the assigned
  1022. value is truncated to the target length minus one. The target will
  1023. always contain 0X as a terminator. In ASSERT(x, n) and HALT(n), the
  1024. interpretation of n is left to the underlying system implementation.
  1025.  
  1026.  
  1027. 11. Modules
  1028.  
  1029. A module is a collection of declarations of constants, types, variables,
  1030. and procedures, together with a sequence of statements for the purpose
  1031. of assigning initial values to the variables. A module constitutes a
  1032. text that is compilable as a unit.
  1033.  
  1034. Module   = MODULE ident ";" [ImportList] DeclarationSequence
  1035.       [BEGIN StatementSequence] END ident ".".
  1036. ImportList   = IMPORT Import {"," Import} ";".
  1037. Import   = [ident ":="] ident.
  1038.  
  1039. The import list specifies the names of the imported modules. If a module
  1040. A is imported by a module M and A exports an identifier x, then x is
  1041. referred to as A.x within M. If A is imported as B := A, the object x
  1042. must be referenced as B.x. This allows short alias names in qualified
  1043. identifiers. A module must not import itself. Identifiers that are to be
  1044. exported (i.e. that are to be visible in client modules) must be marked
  1045. by an export mark in their declaration (see Chapter 4).
  1046.  
  1047.   The statement sequence following the symbol BEGIN is executed when the
  1048. module is added to a system (loaded), which is done after the imported
  1049. modules have been loaded. It follows that cyclic import of modules is
  1050. illegal. Individual (parameterless and exported) procedures can be
  1051. activated from the system, and these procedures serve as commands (see
  1052. Appendix D1).
  1053.  
  1054. MODULE Trees;   (* exports: Tree, Node, Insert, Search, Write, Init *)
  1055.   IMPORT Texts, Oberon;  (* exports read-only: Node.name *)
  1056.  
  1057.   TYPE
  1058.     Tree* = POINTER TO Node;
  1059.     Node* = RECORD
  1060.       name-: POINTER TO ARRAY OF CHAR;
  1061.       left, right: Tree
  1062.     END;
  1063.  
  1064.   VAR w: Texts.Writer;
  1065.  
  1066.   PROCEDURE (t: Tree) Insert* (name: ARRAY OF CHAR);
  1067.     VAR p, father: Tree;
  1068.   BEGIN p := t;
  1069.     REPEAT father := p;
  1070.       IF name = p.name^ THEN RETURN END;
  1071.       IF name < p.name^ THEN p := p.left ELSE p := p.right END
  1072.     UNTIL p = NIL;
  1073.     NEW(p); p.left := NIL; p.right := NIL; NEW(p.name, LEN(name)+1); COPY(name,
  1074. p.name^);
  1075.     IF name < father.name^ THEN father.left := p ELSE father.right := p END
  1076.   END Insert;
  1077.  
  1078.   PROCEDURE (t: Tree) Search* (name: ARRAY OF CHAR): Tree;
  1079.     VAR p: Tree;
  1080.   BEGIN p := t;
  1081.     WHILE (p # NIL) & (name # p.name^) DO
  1082.       IF name < p.name^ THEN p := p.left ELSE p := p.right END
  1083.     END;
  1084.     RETURN p
  1085.   END Search;
  1086.  
  1087.   PROCEDURE (t: Tree) Write*;
  1088.   BEGIN
  1089.     IF t.left # NIL THEN t.left.Write END;
  1090.     Texts.WriteString(w, t.name^); Texts.WriteLn(w); Texts.Append(Oberon.Log,
  1091. w.buf);
  1092.     IF t.right # NIL THEN t.right.Write END
  1093.   END Write;
  1094.  
  1095.   PROCEDURE Init* (t: Tree);
  1096.   BEGIN NEW(t.name, 1); t.name[0] := 0X; t.left := NIL; t.right := NIL
  1097.   END Init;
  1098.  
  1099. BEGIN Texts.OpenWriter(w)
  1100. END Trees.
  1101.  
  1102. Appendix A: Definition of terms
  1103.  
  1104.  
  1105. Integer types  SHORTINT, INTEGER, LONGINT
  1106. Real types  REAL, LONGREAL
  1107. Numeric types  integer types, real types
  1108.  
  1109.  
  1110. Same types
  1111.  
  1112. Two variables a and b with types Ta and Tb are of the same type if
  1113.  
  1114. 1.  Ta and Tb are both denoted by the same type identifier, or
  1115. 2.  Ta is declared to equal Tb in a type declaration of the form Ta =
  1116. Tb, or
  1117. 3.  a and b appear in the same identifier list in a variable, record
  1118. field, or formal parameter declaration
  1119.   and are not open arrays.
  1120.  
  1121.  
  1122. Equal types
  1123.  
  1124. Two types Ta and Tb are equal if
  1125.  
  1126. 1.  Ta and Tb are the same type,  or
  1127. 2.  Ta and Tb are open array types with equal element types, or
  1128. 3.  Ta and Tb are procedure types whose formal parameter lists match.
  1129.  
  1130.  
  1131. Type inclusion
  1132.  
  1133. Numeric types include (the values of) smaller numeric types according to
  1134. the following hierarchy:
  1135.  
  1136.   LONGREAL >= REAL >= LONGINT >= INTEGER >= SHORTINT
  1137.  
  1138.  
  1139. Type extension (base type)
  1140.  
  1141. Given a type declaration Tb = RECORD (Ta) ... END, Tb is a direct
  1142. extension of Ta, and Ta is a direct base type of Tb. A type Tb is an
  1143. extension of a type Ta (Ta is a base type of Tb) if
  1144.  
  1145. 1.  Ta and Tb are the same types, or
  1146. 2.  Tb is a direct extension of an extension of Ta
  1147.  
  1148. If Pa = POINTER TO Ta and Pb = POINTER TO Tb, Pb is an extension of Pa
  1149. (Pa is a base type of Pb) if Tb is an extension of Ta.
  1150.  
  1151.  
  1152. Assignment compatible
  1153.  
  1154. An expression e of type Te is assignment compatible with a variable v of
  1155. type Tv if one of the following conditions hold:
  1156.  
  1157. 1.  Te and Tv are the same type;
  1158. 2.  Te and Tv are numeric types and Tv includes Te;
  1159. 3.  Te and Tv are record types and Te is an extension of Tv and the
  1160. dynamic type of v is Tv ;
  1161. 4.  Te and Tv are pointer types and Te is an extension of Tv;
  1162. 5.  Tv is a pointer or a procedure type and e is NIL;
  1163. 6.  Tv is ARRAY n OF CHAR, e is a string constant with m characters, and
  1164. m < n;
  1165. 7.  Tv is a procedure type and e is the name of a procedure whose formal
  1166. parameters match those of Tv.
  1167.  
  1168.  
  1169. Array compatible
  1170.  
  1171. An actual parameter a of type Ta is array compatible with a formal
  1172. parameter f of type Tf if
  1173.  
  1174. 1.  Tf and Ta are the same type, or
  1175. 2.  Tf is an open array, Ta is any array, and their element types are
  1176. array compatible, or
  1177. 3.  Tf is ARRAY OF CHAR and a is a string.
  1178.  
  1179.  
  1180. Expression compatible
  1181.  
  1182. For a given operator, the types of its operands are expression
  1183. compatible if they conform to the following table (which shows also the
  1184. result type of the expression). Character arrays that are to be compared
  1185. must contain 0X as a terminator. Type T1 must be an extension of type
  1186. T0:
  1187.  
  1188. operator   first operand  second operand   result type
  1189. + - *  numeric  numeric  smallest numeric type including both operands
  1190. /  numeric  numeric  smallest real type including both operands
  1191. + - * /  SET  SET  SET
  1192. DIV MOD  integer  integer  smallest integer type including both operands
  1193. OR & ~  BOOLEAN  BOOLEAN  BOOLEAN
  1194. = # < <= > >=  numeric  numeric  BOOLEAN
  1195.   CHAR  CHAR  BOOLEAN
  1196.   character array, string  character array, string  BOOLEAN
  1197. = #  BOOLEAN  BOOLEAN  BOOLEAN
  1198.   SET  SET  BOOLEAN
  1199.   NIL, pointer type T0 or T1  NIL, pointer type T0 or T1  BOOLEAN
  1200.   procedure type T, NIL  procedure type T, NIL  BOOLEAN
  1201. IN  integer  SET  BOOLEAN
  1202. IS  type T0  type T1  BOOLEAN
  1203.  
  1204.  
  1205. Matching formal parameter lists
  1206. Two formal parameter lists match if
  1207. 1.  they have the same number of parameters, and
  1208. 2.  they have either the same function result type or none, and
  1209. 3.  parameters at corresponding positions have equal types, and
  1210. 4.  parameters at corresponding positions are both either value or variable
  1211. parameters.
  1212.  
  1213.  
  1214. Appendix B: Syntax of Oberon-2
  1215.  
  1216.  
  1217. Module   =   MODULE ident ";" [ImportList] DeclSeq  [BEGIN StatementSeq] END
  1218. ident ".".
  1219. ImportList   =   IMPORT [ident ":="] ident {"," [ident ":="] ident} ";".
  1220. DeclSeq   =   { CONST {ConstDecl ";" } | TYPE {TypeDecl ";"} | VAR {VarDecl
  1221. ";"}} {ProcDecl ";" | ForwardDecl ";"}.
  1222. ConstDecl  =   IdentDef "=" ConstExpr.
  1223. TypeDecl  =   IdentDef "=" Type.
  1224. VarDecl  =   IdentList ":" Type.
  1225. ProcDecl   =   PROCEDURE [Receiver] IdentDef [FormalPars] ";" DeclSeq [BEGIN
  1226. StatementSeq] END ident.
  1227. ForwardDecl  =   PROCEDURE "^" [Receiver] IdentDef [FormalPars].
  1228. FormalPars   =   "(" [FPSection {";" FPSection}] ")" [":" Qualident].
  1229. FPSection   =   [VAR] ident {"," ident} ":" Type.
  1230. Receiver  =   "(" [VAR] ident ":" ident ")".
  1231. Type   =   Qualident
  1232.   |   ARRAY [ConstExpr {"," ConstExpr}] OF Type
  1233.   |   RECORD ["("Qualident")"] FieldList {";" FieldList} END
  1234.   |   POINTER TO Type
  1235.   |   PROCEDURE [FormalPars].
  1236. FieldList   =   [IdentList ":" Type].
  1237. StatementSeq  =   Statement {";" Statement}.
  1238. Statement   =  [  Designator ":=" Expr
  1239.   |    Designator ["(" [ExprList] ")"]
  1240.   |    IF Expr THEN StatementSeq {ELSIF Expr THEN StatementSeq} [ELSE StatementSeq]
  1241. END
  1242.   |    CASE Expr OF Case {"|" Case} [ELSE StatementSeq] END
  1243.   |    WHILE Expr DO StatementSeq END
  1244.   |    REPEAT StatementSeq UNTIL Expr
  1245.   |    FOR ident ":=" Expr TO Expr [BY ConstExpr] DO StatementSeq END
  1246.   |    LOOP StatementSeq END
  1247.   |    WITH Guard DO StatementSeq {"|" Guard DO StatementSeq} [ELSE StatementSeq]
  1248. END
  1249.   |    EXIT
  1250.   |    RETURN [Expr]
  1251.       ].
  1252. Case   =   [CaseLabels {"," CaseLabels} ":" StatementSeq].
  1253. CaseLabels   =   ConstExpr [".." ConstExpr].
  1254. Guard  =   Qualident ":" Qualident.
  1255. ConstExpr  =   Expr.
  1256. Expr   =   SimpleExpr [Relation SimpleExpr].
  1257. SimpleExpr  =   ["+" | "-"] Term {AddOp Term}.
  1258. Term   =   Factor {MulOp Factor}.
  1259. Factor   =   Designator ["(" [ExprList] ")"] | number | character | string |
  1260. NIL | Set | "(" Expr ")" | " ~ " Factor.
  1261. Set  =   "{" [Element {"," Element}] "}".
  1262. Element   =   Expr [".." Expr].
  1263. Relation   =   "=" | "#" | "<" | "<=" | ">" | ">=" | IN | IS.
  1264. AddOp   =   "+" | "-" | OR.
  1265. MulOp   =   " * " | "/" | DIV | MOD | "&".
  1266. Designator   =   Qualident {"." ident | "[" ExprList "]" | " ^ " | "(" Qualident
  1267. ")"}.
  1268. ExprList   =   Expr {"," Expr}.
  1269. IdentList   =   IdentDef {"," IdentDef}.
  1270. Qualident   =   [ident "."] ident.
  1271. IdentDef   =   ident [" * " | "-"].
  1272.  
  1273.  
  1274. Appendix C: The module SYSTEM
  1275.  
  1276. The module SYSTEM contains certain types and procedures that are
  1277. necessary to implement low-level operations particular to a given
  1278. computer and/or implementation. These include for example facilities for
  1279. accessing devices that are controlled by the computer, and facilities to
  1280. break the type compatibility rules otherwise imposed by the language
  1281. definition. It is strongly recommended to restrict their use to specific
  1282. modules (called low-level modules). Such modules are inherently
  1283. non-portable, but easily recognized due to the identifier SYSTEM
  1284. appearing in their import list. The following specifications hold for
  1285. the implementation of Oberon-2 on the Ceres computer.
  1286.  
  1287.   Module SYSTEM exports a type BYTE with the following characteristics:
  1288. Variables of type CHAR or SHORTINT can be assigned to variables of type
  1289. BYTE. If a formal variable parameter is of type ARRAY OF BYTE then the
  1290. corresponding actual parameter may be of any type.
  1291.  
  1292.   Another type exported by module SYSTEM is the type PTR. Variables of
  1293. any pointer type may be assigned to variables of type PTR. If a formal
  1294. variable parameter is of type PTR, the actual parameter may be of any
  1295. pointer type.
  1296.  
  1297.   The procedures contained in module SYSTEM are listed in the following
  1298. tables. Most of them correspond to single instructions compiled as
  1299. in-line code. For details, the reader is referred to the processor
  1300. manual. v stands for a variable, x, y, a, and n for expressions, and T
  1301. for a type.
  1302.  
  1303. Function procedures
  1304.  
  1305. Name  Argument types  Result type  Function
  1306.  
  1307. ADR(v)  any  LONGINT  address of variable v
  1308. BIT(a, n)  a: LONGINT  BOOLEAN  bit n of Mem[a]
  1309.   n: integer
  1310. CC(n)  integer constant  BOOLEAN  condition n (0 <= n <= 15)
  1311. LSH(x, n)  x: integer, CHAR, BYTE  type of x  logical shift
  1312.   n: integer
  1313. ROT(x, n)  x: integer, CHAR, BYTE  type of x  rotation
  1314.   n: integer
  1315. VAL(T, x)  T, x: any type  T  x interpreted as of type T
  1316.  
  1317. Proper procedures
  1318.  
  1319. Name  Argument types  Function
  1320.  
  1321. GET(a, v)  a: LONGINT; v: any basic type,  v := Mem[a]
  1322.   pointer, procedure type
  1323. PUT(a, x)  a: LONGINT; x: any basic type,  Mem[a] := x
  1324.   pointer, procedure type
  1325. GETREG(n, v)  n: integer constant; v: any basic type,  v := Register n
  1326.   pointer, procedure type
  1327. PUTREG(n, x)  n: integer constant; x: any basic type,  Register n := x
  1328.   pointer, procedure type
  1329. MOVE(a0, a1, n)  a0, a1: LONGINT; n: integer  Mem[a1.. a1+n-1] := Mem[a0.. a0+n-1]
  1330. NEW(v, n)  v: any pointer; n: integer  allocate storage block of n bytes
  1331.     assign its address to v
  1332.  
  1333. Appendix D: The Oberon Environment
  1334.  
  1335. Oberon-2 programs usually run in an environment that provides command
  1336. activation, garbage collection, dynamic loading of modules, and certain
  1337. run time data structures. Although not part of the language, this
  1338. environment contributes to the power of Oberon-2 and is to some degree
  1339. implied by the language definition. Appendix D describes the essential
  1340. features of a typical Oberon environment and provides implementation
  1341. hints. More details can be found in [1], [2], and [3].
  1342.  
  1343.  
  1344. D1. Commands
  1345.  
  1346. A command is any parameterless procedure P that is exported from a
  1347. module M. It is denoted by M.P and can be activated under this name from
  1348. the shell of the operating system. In Oberon, a user invokes commands
  1349. instead of programs or modules. This gives him a finer grain of control
  1350. and allows modules with multiple entry points. When a command M.P is
  1351. invoked, the module M is dynamically loaded unless it is already in
  1352. memory (see D2) and the procedure P is executed. When P terminates, M
  1353. remains loaded. All global variables and data structures that can be
  1354. reached from global pointer variables in M retain their values. When P
  1355. (or another command of M) is invoked again, it may continue to use these
  1356. values.
  1357.  
  1358.   The following module demonstrates the use of commands. It implements
  1359. an abstract data structure Counter that encapsulates a counter variable
  1360. and provides commands to increment and print its value.
  1361.  
  1362. MODULE Counter;
  1363.   IMPORT Texts, Oberon;
  1364.  
  1365.   VAR
  1366.     counter: LONGINT;
  1367.     w: Texts.Writer;
  1368.  
  1369.   PROCEDURE Add*;   (* takes a numeric argument from the command line *)
  1370.     VAR s: Texts.Scanner;
  1371.   BEGIN
  1372.     Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos);
  1373.     Texts.Scan(s);
  1374.     IF s.class = Texts.Int THEN INC(counter, s.i) END
  1375.   END Add;
  1376.  
  1377.   PROCEDURE Write*;
  1378.   BEGIN
  1379.     Texts.WriteInt(w, counter, 5); Texts.WriteLn(w);
  1380.     Texts.Append(Oberon.Log, w.buf)
  1381.   END Write;
  1382.  
  1383. BEGIN counter := 0; Texts.OpenWriter(w)
  1384. END Counter.
  1385.  
  1386. The user may execute the following two commands:
  1387.  
  1388. Counter.Add   n   adds the value n to the variable counter
  1389. Counter.Write   writes the current value of counter to the screen
  1390.  
  1391. Since commands are parameterless they have to get their arguments from
  1392. the operating system. In general, commands are free to take arguments
  1393. from everywhere (e.g. from the text following the command, from the most
  1394. recent selection, or from a marked viewer). The command Add uses a
  1395. scanner (a data type provided by the Oberon system) to read the value
  1396. that follows it on the command line.
  1397.  
  1398.   When Counter.Add is invoked for the first time, the module Counter is
  1399. loaded and its body is executed. Every call of Counter.Add n increments
  1400. the variable counter by n. Every call of Counter.Write writes the
  1401. current value of counter to the screen.
  1402.  
  1403.   Since a module remains loaded after the execution of its commands,
  1404. there must be an explicit way to unload it (e.g. when the user wants to
  1405. substitute the loaded version by a recompiled version.) The Oberon
  1406. system provides a command to do that.
  1407.  
  1408.  
  1409. D2. Dynamic Loading of Modules
  1410.  
  1411. A loaded module may invoke a command of a still unloaded module by
  1412. specifying its name as a string. The specified module is then
  1413. dynamically loaded and the designated command is executed. Dynamic
  1414. loading allows the user to start a program as a small set of basic
  1415. modules and to extend it by adding further modules at run time as the
  1416. need becomes evident.
  1417.  
  1418.   A module M0 may cause the dynamic loading of a module M1 without
  1419. importing it. M1 may of course import and use M0, but M0 need not know
  1420. about the existence of M1. M1 can be a module that is designed and
  1421. implemented long after M0.
  1422.  
  1423.  
  1424. D3. Garbage Collection
  1425.  
  1426. In Oberon-2, the predeclared procedure NEW is used to allocate data
  1427. blocks in free memory. There is, however, no way to explicitly dispose
  1428. an allocated block. Rather, the Oberon environment uses a garbage
  1429. collector to find the blocks that are not used any more and to make them
  1430. available for allocation again. A block is in use as long as it can be
  1431. reached from a global pointer variable via a pointer chain. Cutting this
  1432. chain (e.g., setting a pointer to NIL) makes the block collectable.
  1433.  
  1434.   A garbage collector frees a programmer from the non-trivial task of
  1435. deallocating data structures correctly and thus helps to avoid errors.
  1436. However, it requires information about dynamic data at run time (see
  1437. D5).
  1438.  
  1439.  
  1440. D4. Browser
  1441.  
  1442. The interface of a module (the declaration of the exported objects) is
  1443. extracted from the module by a so-called browser which is a separate
  1444. tool of the Oberon environment. For example, the browser produces the
  1445. following interface of the module Trees from Ch. 11.
  1446.  
  1447. DEFINITION Trees;
  1448.   TYPE
  1449.     Tree = POINTER TO Node;
  1450.     Node = RECORD
  1451.       name: POINTER TO ARRAY OF CHAR;
  1452.       PROCEDURE (t: Tree) Insert (name: ARRAY OF CHAR);
  1453.       PROCEDURE (t: Tree) Search (name: ARRAY OF CHAR): Tree;
  1454.       PROCEDURE (t: Tree) Write;
  1455.     END;
  1456.   PROCEDURE Init (VAR t: Tree);
  1457. END Trees.
  1458.  
  1459. For a record type, the browser also collects all procedures bound to
  1460. this type and shows their declaration in the record type declaration.
  1461.  
  1462.  
  1463. D5. Run Time Data Structures
  1464.  
  1465. Certain information about records has to be available at run time: The
  1466. dynamic type of records is needed for type tests and type guards. A
  1467. table with the addresses of the procedures bound to a record is needed
  1468. for calling them. Finally, the garbage collector needs information about
  1469. the location of pointers in dynamically allocated records. All that
  1470. information is stored in so-called type descriptors of which there is
  1471. one for every record type at run time. The following paragraphs show a
  1472. possible implementation of type descriptors.
  1473.  
  1474.   The dynamic type of a record corresponds to the address of its type
  1475. descriptor. For dynamically allocated records this address is stored in
  1476. a so-called type tag which precedes the actual record data and which is
  1477. invisible for the programmer. If t is a variable of type CenterTree (see
  1478. example in Ch. 6) Figure D5.1 shows one possible implementation of the
  1479. run time data structures.
  1480.  
  1481.  
  1482. Fig. D5.1  A variable t of type CenterTree, the record t^ it points to,
  1483. and its type descriptor
  1484.  
  1485. Since both the table of procedure addresses and the table of pointer
  1486. offsets must have a fixed offset from the type descriptor address, and
  1487. since both may grow when the type is extended and further procedures and
  1488. pointers are added, the tables are located at the opposite ends of the
  1489. type descriptor and grow in different directions.
  1490.  
  1491.   A type-bound procedure t.P is called as t^.tag^.ProcTab[IndexP]. The
  1492. procedure table index of every type-bound procedure is known at compile
  1493. time. A type test v IS T is translated into
  1494. v^.tag^.BaseTypes[ExtensionLevelT] = TypeDescrAdrT. Both the extension
  1495. level of a record type and the address of its type descriptor are known
  1496. at compile time. For example, the extension level of Node is 0 (it has
  1497. no base type), and the extension level of CenterNode is 1.
  1498.  
  1499. [1]  N.Wirth, J.Gutknecht: The Oberon System. Software Practice and
  1500. Experience 19, 9, Sept. 1989
  1501.  
  1502. [2]  M.Reiser: The Oberon System. User Guide and Programming Manual.
  1503. Addison-Wesley, 1991
  1504.  
  1505. [3]  C.Pfister, B.Heeb, J.Templ: Oberon Technical Notes. Report 156, ETH
  1506. Zürich, March 1991
  1507.